<?php

/*
 * Manager/EmployeManager.php
 */

namespace RHX\Model\Manager;

use Zend\Db\Adapter\Adapter;
use RHX\Helper\RHDateTime;
use RHX\Model\Object\XRules;

class EmployeManager {

    protected $adapter		 = null;
    protected $uploadDirectory	 = array(
	'employe' => array(
	    'photo'			 => 'public/upload/photo/',
	    'rib'			 => 'public/upload/rib/',
	    'cv'			 => 'public/upload/cv/',
	    'titre_de_sejour'	 => 'public/upload/sejournum/',
	    'contrat'		 => 'public/upload/contrat/',
	    'avenant'		 => 'public/upload/avenant/'
	),
    );

    /**
     * Constructeur
     * 
     * @param \Zend\Db\Adapter\Adapter $adapter
     */
    public function __construct(Adapter $adapter) {
	$this->adapter = $adapter;
    }

    /**
     * Adapteur de base de données
     * 
     * @return Adapter
     */
    public function getAdapter() {
	return $this->adapter;
    }

    /**
     * Transfert définitif d'un employé
     * 
     * @param int $matricule
     * @param int $siteId
     * @param string $date
     * @return \RHX\Model\Object\Employe
     */
    private function __transfertDefinitif($matricule, $siteId, $date = null) {
	$employe			 = $this->getEmploye($matricule);
	$newEmploye			 = $this->changeSite($this->cloneEmploye($employe), $siteId);
	$dataAvenant			 = $this->createNewAvenant($employe, $siteId, $date);
	$dataAvenant['new']->matricule	 = $newEmploye->matricule;
	$dispo				 = $this->cloneDisponibilite($employe, $newEmploye);
	$templates			 = $this->addToPlanningTypes($newEmploye, $siteId);
	$plannings			 = $this->addToPlanningSemaines($newEmploye, $date);
	return array(
	    'old'		 => $employe,
	    'new'		 => $newEmploye,
	    'avenantOld'	 => $dataAvenant['old'],
	    'avenantNew'	 => $dataAvenant['new'],
	    'dispo'		 => $dispo,
	    'templates'	 => $templates,
	    'plannings'	 => $plannings,
	);
    }

    /**
     * Transfert de site<br>
     * Retourne un tableau contenant les informations suivantes :<br>
     * Employé en cours, Nouvel Employé, Avenants copiés (Nouveaux avenants, Historique des avenants, 
     * Fichiers des avenants), Diponibilité copiée, Planning Types copiés, Planning Semaines copiés.
     * 
     * @param int $matricule
     * @param int $siteId
     * @param string $date
     * @return array
     */
    public function transfertSite($matricule, $siteId, $date = null) {
	// Récupération de l'employé
	$employe	 = $this->getEmploye($matricule);
	// Ajouter l'avenant Changement de site
	$tr		 = $this->addAvenantChangementSite($employe, $siteId, $date);
	// Dupliquer l'employe et changer son site id
	$newEmploye	 = $this->cloneEmploye($employe, $siteId);
	// Dupliquer les visites et entretiens
	$visites	 = $this->cloneSante($employe, $newEmploye);
	$entretiens	 = $this->cloneEntretien($employe, $newEmploye);
	// Dupliquer les fichiers
	$files		 = $this->cloneFiles($employe);
	// Dupliquer les avenants : avenants, historiques et fichiers
	$avenants	 = $this->cloneAvenants($employe, $newEmploye);
	// Cloture du contrat de l'ancien employé
	$this->closeContrat($employe, $date);
	// MAJ info employe
	$this->updateInfoTransfertEmploye($employe);
	// Dupliquer les disponibilités
	$dispo		 = $this->cloneDisponibilite($employe, $newEmploye);
	// Ajouter aux plannings type du site d'arrivée
	$templates	 = $this->addToPlanningTypes($newEmploye, $siteId);
	// Ajouter aux plannings semaine du site d'arrivée
	$date		 = is_null($date) ? date('Y-m-d') : $date;
	$plannings	 = $this->addToPlanningSemaines($newEmploye, $date);
	//MAJ planning semaine site de départ
	$planningsOld	 = $this->setESPlanningSemaines($employe, $date);
	$this->erasePlanningSemaines($employe, $date);

	return array(
	    'employe'	 => $employe,
	    'newEmploye'	 => $newEmploye,
	    'files'		 => $files,
	    'avenants'	 => $avenants,
	    'dispo'		 => $dispo,
	    'templates'	 => $templates,
	    'plannings'	 => $plannings,
	    'entretiens'	 => $entretiens,
	    'visites'	 => $visites,
	    'transfert'	 => $tr,
	);
    }

    /* Combine les methode de suppression d'un employé transféré
     * @param int $matricule
     */

    public function cancelTransfertSite($matricule, $siteId) {
	//table
	$tableEmploye = new \RHX\Model\Table\EmployeTable($this->getAdapter());

	// Récupération des  entité de l' employés
	$employe	 = $this->getEmploye($matricule);
	$employeDest	 = $tableEmploye->getOneByTransfert($matricule);

	// suppression des PT
	//suppression des PS
	//update transfert
	$employe->transfert = (abs($employe->transfert) == 9999) ? 0 : abs($employe->transfert);
	$tableEmploye->save($employe);

	var_dump($employe);
	var_dump($employeDest);
	die;
	return array(
	    'debug' => '',
	);
	$employeDest = $tableEmploye->getOneByTransfert($matricule);

	$this->deleteEmploye($employeDest->matricule);

	//update transfert
	if ($employe->transfert === -9999) {
	    $employe->transfert = 0;
	}
	else {
	    $employe->transfert = abs($employe->transfert);
	}
	$tableEmploye->save($employe);

	//var_dump($employe);
	//var_dump($employeDest);
	die;
	return array(
	    'debug' => '',
	);
    }

    /* Supprime définitivement un employé et les entités/fichiers qui y sont reliés/rattachés 
     * @param int $matricule
     * 
     */

    public function deleteEmploye($matricule) {
	//table
	$tableEmploye	 = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	$tableEmployeTpl = new \RHX\Model\Table\EmployeTemplateTable($this->getAdapter());
	$tablePS	 = new \RHX\Model\Table\PlanningSemaineTable($this->getAdapter());
	$tableAv	 = new \RHX\Model\Table\AvenantTable($this->getAdapter());
	$tableAvHist	 = new \RHX\Model\Table\AvenantHistoryTable($this->getAdapter());


	//suppression des fichiers (photo, contrat, avenants, ...)
	// suppression des PT
	// DELETE FROM rh_employe_template WHERE matricule = 293
	$tableEmployeTpl->executeQuery("DELETE FROM rh_employe_template WHERE matricule =  $matricule ");

	// suppression des PS
	// DELETE FROM rh_planning_semaine WHERE matricule = 293
	$tablePS->executeQuery("DELETE FROM rh_planning_semaine WHERE matricule = $matricule ");

	//suppression Instruction de paye
	// suppression des avenants
	//suppression des employé 
	$tableEmploye->erase($matricule);
    }

    /**
     * Changement de site
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param int $siteId
     * @return \RHX\Model\Object\Employe
     */
    private function changeSite(\RHX\Model\Object\Employe $employe, $siteId) {
	$employe->site_id = $siteId;
	return $employe;
    }

    /**
     * Enregistrement des informations de l'employé dans la base de données<br>
     * Retourne l'identifiant de l'employé enregistrer
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @return int
     */
    private function saveEmploye(\RHX\Model\Object\Employe $employe) {
	$tableEmploye = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	return $tableEmploye->save($employe);
    }

    /**
     * Cloner les informations d'un employé
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param int|null $siteId
     * @param boolean $actif
     * @return \RHX\Model\Object\Employe
     */
    private function cloneEmploye(\RHX\Model\Object\Employe $employe, $siteId = null, $actif = true) {
	$data			 = $employe->getArrayCopy();
	$clone			 = new \RHX\Model\Object\Employe($this->getAdapter(), $data);
	$tableEmploye		 = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	$clone->matricule	 = 0; // pour créer un nouvel employé dans la base
	$clone->transfert	 = $employe->matricule;
	$clone->actif		 = ($actif == TRUE) ? 1 : 0;
	$clone->indice		 = ((int) $employe->indice) + 1;
	$clone->site_id		 = (!is_null($tableEmploye)) ? $siteId : $clone->site_id;
	$clone->matricule	 = $tableEmploye->save($clone);
	return $clone;
    }

    /**
     * Cloner tous les entretiens de l'employé
     * 
     * @param \RHX\Model\Object\Employe $old
     * @param \RHX\Model\Object\Employe $new
     * @return array
     */
    private function cloneEntretien(\RHX\Model\Object\Employe $old, \RHX\Model\Object\Employe $new) {
	$entretients	 = $old->getEntretien(true);
	$array		 = array();
	$tableEntretien	 = new \RHX\Model\Table\EmployeEntretienTable($this->getAdapter());
	foreach ($entretients as $e) {
	    $e->matricule	 = $new->matricule;
	    $e->id		 = 0;
	    $e->id		 = $tableEntretien->save($e);
	    $array[]	 = $e;
	}
	return $array;
    }

    /**
     * Cloner les informations de visite médicale
     * 
     * @param \RHX\Model\Object\Employe $old
     * @param \RHX\Model\Object\Employe $new
     * @return array
     */
    private function cloneSante(\RHX\Model\Object\Employe $old, \RHX\Model\Object\Employe $new) {
	$visites	 = $old->getVisiteMedicale(true);
	$array		 = array();
	$tableVisite	 = new \RHX\Model\Table\EmployeSanteTable($this->getAdapter());
	foreach ($visites as $v) {
	    $v->matricule	 = $new->matricule;
	    $v->id		 = 0;
	    $v->id		 = $tableVisite->save($v);
	    $array[]	 = $v;
	}
	return $array;
    }

    /**
     * Dupliquer les disponibilités de l'employé
     * 
     * @param \RHX\Model\Object\Employe $old
     * @param \RHX\Model\Object\Employe $new
     * @return \RHX\Model\Object\EmployeDisponibilite
     */
    private function cloneDisponibilite(\RHX\Model\Object\Employe $old, \RHX\Model\Object\Employe $new) {
	$dispoOld		 = $old->getDisponibilite();
	$dispo			 = new \RHX\Model\Object\EmployeDisponibilite($dispoOld->getArrayCopy());
	$dispo->matricule	 = $new->matricule;
	$tableDisponibilite	 = new \RHX\Model\Table\EmployeDisponibiliteTable($this->getAdapter());
	$dispo->id		 = 0;
	$dispo->id		 = $tableDisponibilite->save($dispo);
	return $dispo;
    }

    /**
     * Copier les diplomes d'un employé à un autre
     * 
     * @param \RHX\Model\Object\Employe $old
     * @param \RHX\Model\Object\Employe $new
     * @return array
     */
    private function cloneDiplomes(\RHX\Model\Object\Employe $old, \RHX\Model\Object\Employe $new) {
	$diplomes		 = $old->getDiplomes();
	$tableEmployeDiplome	 = new \RHX\Model\Table\EmployeDiplomeTable($this->getAdapter());
	$diplomas		 = array();
	foreach ($diplomes as $d) {
	    $empDipl	 = new \RHX\Model\Object\EmployeDiplome($this->getAdapter(), array(
		'matricule'	 => $new->matricule,
		'diplome_id'	 => $d->id,
		'remarque'	 => date('Y-m-d') . ' Chg Site',
	    ));
	    $empDipl->id	 = $tableEmployeDiplome->save($empDipl);
	    $diplomas[]	 = $d;
	}
	return $diplomas;
    }

    /**
     * Copier les formations d'un employé à un autre
     * 
     * @param \RHX\Model\Object\Employe $old
     * @param \RHX\Model\Object\Employe $new
     * @return array
     */
    private function cloneFormations(\RHX\Model\Object\Employe $old, \RHX\Model\Object\Employe $new) {
	$formations		 = $old->getFormations();
	$tableEmployeFormation	 = new \RHX\Model\Table\EmployeFormationTable($this->getAdapter());
	$formationas		 = array();
	foreach ($formations as $f) {
	    $empForm	 = new \RHX\Model\Object\EmployeFormation($this->getAdapter(), array(
		'matricule'	 => $new->matricule,
		'formation_id'	 => $f->id,
		'remarque'	 => date('Y-m-d') . ' Chg Site',
	    ));
	    $empForm->id	 = $tableEmployeFormation->save($empForm);
	    $formationas[]	 = $f;
	}
	return $formationas;
    }

    /**
     * Copier tous les données des avenants<br>
     * Retourne un tableau contenant les informations suivantes :
     * <ul style='color:red;'><li>Nouveaux avenants,</li><li>Historique des avenants,</li><li>Fichiers des avenants</li></ul>
     * 
     * @param \RHX\Model\Object\Employe $old
     * @param \RHX\Model\Object\Employe $new
     * @return array
     */
    private function cloneAvenants(\RHX\Model\Object\Employe $old, \RHX\Model\Object\Employe $new) {
	$avenants	 = $this->cloneAvenantsDetails($old);
	$history	 = $this->cloneAvenantHistory($old, $new, $avenants);
	$files		 = $this->cloneAvenantFile($avenants);
	return array(
	    'avenants'	 => $avenants,
	    'history'	 => $history,
	    'files'		 => $files,
	);
    }

    /**
     * Copie des details des avenants<br>
     * Retourne un tableau des nouvels avenants
     * 
     * @param \RHX\Model\Object\Employe $old
     * @return \RHX\Model\Object\Avenant
     */
    private function cloneAvenantsDetails(\RHX\Model\Object\Employe $old) {
	$tableAvenant	 = new \RHX\Model\Table\AvenantTable($this->getAdapter());
	$avenants	 = $old->getAvenants('avenant_id ASC');
	$newAvenants	 = array();
	foreach ($avenants as $av) {
	    $avenant		 = new \RHX\Model\Object\Avenant($this->getAdapter(), array(
		'site'		 => $av->site,
		'hebdo'		 => $av->hebdo,
		'taux'		 => $av->taux,
		'debut'		 => $av->debut,
		'fin'		 => $av->fin,
		'poste_id'	 => $av->poste_id,
		'niveau'	 => $av->niveau,
		'echelon'	 => $av->echelon,
		'libelle'	 => $av->libelle,
		'avenant_file'	 => $av->avenant_file,
	    ));
	    $avenant->id		 = $tableAvenant->save($avenant);
	    $newAvenants[$av->id]	 = $avenant;
	}
	return $newAvenants;
    }

    /**
     * Copie de l'historique des avenants<br>
     * Retourne l'historique des avenants du nouvel employé
     * 
     * @param \RHX\Model\Object\Employe $old
     * @param \RHX\Model\Object\Employe $new
     * @param array $avenants
     * @return \RHX\Model\Object\AvenantHistory
     */
    private function cloneAvenantHistory(\RHX\Model\Object\Employe $old, \RHX\Model\Object\Employe $new, $avenants) {
	$avenantHistory	 = $old->getAvenantHistory();
	$tableHistory	 = new \RHX\Model\Table\AvenantHistoryTable($this->getAdapter());
	$historic	 = array();
	$lastHistory = null;
	//var_dump($avenantHistory);
	foreach ($avenantHistory as $h) {
	    //var_dump($h);
	    $history	 = new \RHX\Model\Object\AvenantHistory($this->getAdapter(), array(
		'matricule'	 => $new->matricule,
		'avenant_id'	 => (isset($avenants[(int) $h->avenant_id])) ? $avenants[(int) $h->avenant_id]->id : 0,
		'num'		 => (int) $h->num,
		'commentaire'	 => $h->commentaire,
	    ));
	    $history->id	 = $tableHistory->save($history);
	    $historic[]	 = $history;
	    $lastHistory = $h;
	}
	//var_dump($historic);
	if(!is_null($lastHistory)){
	    $avenant = $lastHistory->getAvenant();
	    $this->updateEmploye($new, $avenant);
	}
	return $historic;
    }
    
    /**
     * Mise à jour des informations des avenants de l'employé
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param \RHX\Model\Object\Avenant $avenant
     */
    private function updateEmploye($employe, $avenant){
	$table = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	$employe->avenant_id = $avenant->id;
	$table->save($employe);
    }

    /**
     * Copie des fichiers des avenants
     * 
     * @param array $avenants
     * @return array
     */
    private function cloneAvenantFile($avenants) {
	$path		 = $this->uploadDirectory['employe']['avenant'];
	$tableAvenant	 = new \RHX\Model\Table\AvenantTable($this->getAdapter());
	$files		 = array();
	foreach ($avenants as $a) {
	    $oldFile = $path . $a->avenant_file;
	    $newFile = $path . 'avenant-' . $a->id;
	    if ($this->fileCopy($oldFile, $newFile)) {
		$a->avenant_file = 'avenant-' . $a->id;
		$tableAvenant->save($a);
		$files[]	 = "Copie de $oldFile ves $newFile";
	    }
	}
	return $files;
    }

    /**
     * Copie de tous les fichiers<br>
     * <ul>
     * 	<li>Contrat</li>
     * 	<li>Photo</li>
     * 	<li>RIB</li>
     * 	<li>CV</li>
     * 	<li>Titre de Sejour</li>
     * </ul>
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @return array
     */
    private function cloneFiles(\RHX\Model\Object\Employe $employe) {
	$path		 = $this->uploadDirectory['employe']['avenant'];
	$tableEmploye	 = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	$change		 = false;
	$ext		 = $this->getExtensions($employe);
	$properties	 = array('contrat_file' => 'contrat', 'photo' => 'photo', 'rib' => 'rib', 'cv_path' => 'cv', 'sejour_num_file' => 'sejour');
	$errors		 = array();
	$files		 = array();
	foreach ($properties as $prop => $key) {
	    try {
		if (!$this->isAllowToCopy($employe->$prop, $path)) {
		    continue;
		}
		if ($this->fileCopy($path . $employe->$prop, $path . $key . '-' . '.' . $ext[$key])) {
		    $files[]	 = 'Copie de ' . $employe->$prop . ' vers ' . $key . '-' . '.' . $ext[$key];
		    $employe->$prop	 = $key . '-' . '.' . $ext[$key];
		    $change		 = true;
		}
		else {
		    $errors[] = "Copie impossible du $key";
		}
	    }
	    catch (\Exception $ex) {
		$errors[] = "Copie impossible du $key ({$ex->getMessage()})";
	    }
	}
	if ($change) {
	    $tableEmploye->save($employe);
	}
	return array(
	    'files'	 => $files,
	    'errors' => $errors,
	);
    }

    /**
     * Analyse le nom de fichier si on peut faire la copy
     * 
     * @param string $filename
     * @param string $path
     * @return boolean
     */
    private function isAllowToCopy($filename, $path) {
	if ($filename == '#' || $filename == '' || is_dir($path . $filename)) {
	    return false;
	}
	return true;
    }

    /**
     * Copie de fichier
     * 
     * @param string $src
     * @param string $dest
     * @return boolean
     */
    private function fileCopy($src, $dest) {
	return @copy($src, $dest);
    }

    /**
     * Récupérer les extensions des fichiers
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @return array
     */
    private function getExtensions(\RHX\Model\Object\Employe $employe) {
	return array(
	    'contrat'	 => substr($employe->contrat_file, strrpos($employe->contrat_file, '.')),
	    'photo'		 => substr($employe->photo, strrpos($employe->photo, '.')),
	    'rib'		 => substr($employe->rib, strrpos($employe->rib, '.')),
	    'cv'		 => substr($employe->cv_path, strrpos($employe->cv_path, '.')),
	    'sejour'	 => substr($employe->sejour_num_file, strrpos($employe->sejour_num_file, '.')),
	);
    }

    /**
     * Ajouter un avenant de changement de site
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param int $siteId
     * @param string $date
     * @return \RHX\Model\Object\Avenant
     * @throws \Exception
     */
    private function addAvenantChangementSite(\RHX\Model\Object\Employe $employe, $siteId, $date) {
	// Récupération du dernier avenant
	$avenantEnCours	 = $employe->getTheLastAvenant();
	//var_dump($avenantEnCours);
	$tableAvenant	 = new \RHX\Model\Table\AvenantTable($this->getAdapter());
	$destination	 = $this->getSite($siteId);
	$date		 = new RHDateTime($date);
	if (!is_null($avenantEnCours)) {
	    $tr		 = new \RHX\Model\Object\Avenant($this->getAdapter(), array(
		'site'		 => $siteId,
		'hebdo'		 => 0.0,
		'taux'		 => 0.0,
		'debut'		 => $date,
		'fin'		 => $date,
		'poste_id'	 => $avenantEnCours->poste_id,
		'niveau'	 => 0,
		'echelon'	 => 0,
		'college'	 => 0,
		'libelle'	 => 'TR - ' . $destination->libelle . ' - ' . $date->date('d/m/Y'),
		'avenant_file'	 => '',
	    ));
	    $tr->id = $tableAvenant->save($tr);
	    $this->saveAvenantToHistory($employe, $tr);
	    $avenant	 = new \RHX\Model\Object\Avenant($this->getAdapter(), array(
		'site'		 => $siteId,
		'hebdo'		 => $avenantEnCours->hebdo,
		'taux'		 => $avenantEnCours->taux,
		'debut'		 => $avenantEnCours->debut,
		'fin'		 => $avenantEnCours->fin,
		'poste_id'	 => $avenantEnCours->poste_id,
		'niveau'	 => $avenantEnCours->niveau,
		'echelon'	 => $avenantEnCours->echelon,
		'college'	 => $avenantEnCours->college,
		'libelle'	 => '',
		'avenant_file'	 => '',
	    ));
	    $avenant->id	 = $tableAvenant->save($avenant);
	    $this->saveAvenantToHistory($employe, $avenant, $date);
	    $this->saveAvenantEmploye($employe, $avenant);
            $fin = new RHDateTime($date);
            $fin->modify('previous day');
            $this->closeAvenant($avenantEnCours, $fin);
//	    var_dump($avenant);
//	    var_dump($history);
	    return $avenant;
	}
	else {
	    throw new \Exception("L'avenant en cours est NULL ce qui n'est pas normale.");
	}
    }
    
    /**
     * Ajouter un avenant
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param string $debut
     * @param string $libelle
     * @param boolean $copyBefore
     * @param int $site
     * @return \RHX\Model\Object\Avenant
     */
    public function addAvenant($employe, $debut, $libelle = '', $copyBefore = true, $site = null){
        $tableAvenant = new \RHX\Model\Table\AvenantTable($this->getAdapter());
        $lastAvenant = $employe->getTheLastAvenant();
        $avenant = new \RHX\Model\Object\Avenant($this->getAdapter());
        if(!is_null($lastAvenant)){
            // Cloture du dernier avenant
            $fin = new RHDateTime($debut);
            $fin->modify('previous day');
            $lastAvenant = $this->closeAvenant($lastAvenant, $fin->date());
            if($copyBefore){
                $avenant->avenant_file = $lastAvenant->avenant_file;
                $avenant->college = $lastAvenant->college;
                $avenant->echelon = $lastAvenant->echelon;
                $avenant->hebdo = $lastAvenant->hebdo;
                $avenant->niveau = $lastAvenant->niveau;
                $avenant->poste_id = $lastAvenant->poste_id;
                $avenant->taux = $lastAvenant->taux;
            }
            $avenant->libelle = $libelle;
            $avenant->debut = $debut;
            $avenant->site = is_null($site) ? $lastAvenant->site : (int)$site;
        }
        $avenant->id = $tableAvenant->save($avenant);
        $tableHistory = new \RHX\Model\Table\AvenantHistoryTable($this->getAdapter());
        $history = new \RHX\Model\Object\AvenantHistory($this->getAdapter());
        $history->avenant_id = $avenant->id;
        $history->matricule = $employe->matricule;
        $history->commentaire = (($libelle == '') ? 'Nouvelle avenant ' : $libelle) .' pour #' .$employe->matricule .' le ' . $debut;
        $history->id = $tableHistory->save($history);
        $tableEmploye = new \RHX\Model\Table\EmployeTable($this->getAdapter());
        $employe->avenant_id = $avenant->id;
        $tableEmploye->save($employe);
        return $avenant;
    }
    
    /**
     * Cloture d'un avenant
     * @param \RHX\Model\Object\Avenant $avenant
     * @param string $fin
     * @param \RHX\Model\Table\AvenantTable $table
     * @return \RHX\Model\Object\Avenant
     */
    public function closeAvenant($avenant, $fin, $table = null){
        $table = is_null($table) ? new \RHX\Model\Table\AvenantTable($this->getAdapter()) : $table;
        $avenant->fin = $fin;
        $table->save($avenant);
        return $avenant;
    }

    /**
     * Sauvegarde de l'avenant dans l'historique de l'employé
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param \RHX\Model\Object\Avenant $avenant
     * @return \RHX\Model\Object\AvenantHistory
     */
    private function saveAvenantToHistory($employe, $avenant, $date = null) {
	$historyTable		 = new \RHX\Model\Table\AvenantHistoryTable($this->getAdapter());
	$history		 = new \RHX\Model\Object\AvenantHistory($this->getAdapter());
	$history->avenant_id	 = $avenant->id;
	$history->matricule	 = $employe->matricule;
	$date			 = is_null($date) ? date('Y-m-d') : $date;
	$history->commentaire	 = 'Transfert employe #' . $employe->matricule . ' vers site #' . $avenant->id . ' a la date ' . $date;
	$history->id		 = $historyTable->save($history);
	return $history;
    }
    
    /**
     * Sauvegarder les avenants de l'employe
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param \RHX\Model\Object\Avenant $avenant
     * @return int
     */
    private function saveAvenantEmploye($employe, $avenant){
	$employe->avenant_id = $avenant->id;
	$table = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	$id = $table->save($employe);
	return $id;
    }

    /**
     * Enregistrement de l'avenant en cours dans l'historique des avenants
     * 
     * @param \RHX\Model\Object\Avenant $avenant
     * @param int $matricule
     * @param boolean $changeSite
     * @return \RHX\Model\Object\AvenantHistory
     */
    private function avenantHistory(\RHX\Model\Object\Avenant $avenant, $matricule, $changeSite = true) {
	$tableHistory		 = new \RHX\Model\Table\AvenantHistoryTable($this->getAdapter());
	$history		 = new \RHX\Model\Object\AvenantHistory($this->getAdapter());
	$history->avenant_id	 = $avenant->id;
	$history->matricule	 = $matricule;
	$libelle		 = ($changeSite) ? ' - Changement de site' : 'Nouvelle avenant';
	$history->commentaire	 = date('Y-m-d') . $libelle;
	$history->id		 = $tableHistory->save($history);
	return $history;
    }

    /**
     * Création d'un nouvel avenant à partir d'un employé
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param int $site
     * @param string $date
     * @return Array
     */
    private function createNewAvenant(\RHX\Model\Object\Employe $employe, $site, $date = null) {
	$avenantOld	 = $employe->getAvenant();
	$avenant	 = new \RHX\Model\Object\Avenant($this->getAdapter(), $avenantOld->getArrayCopy());
	$avenant->site	 = $site;
	$avenant->debut	 = (is_null($date)) ? date('Y-m-d') : $date;
	$fin		 = new \RHX\Helper\RHDateTime($avenantOld->fin);
	if ($avenantOld->fin == '0000-00-00') {
	    $avenant->fin = '000-00-00';
	}
	else {
	    $now = new \RHX\Helper\RHDateTime();
	    if ($fin->isGT($now)) {
		$avenant->fin = $avenantOld->fin;
	    }
	    else {
		$avenant->fin = '0000-00-00';
	    }
	}
	$fin->modify('previous day');
	$avenantOld->fin = $fin->date();
	return array(
	    'old'	 => $avenantOld,
	    'new'	 => $avenant,
	);
    }

    /**
     * Récupérer un employé
     * 
     * @param int $matricule
     * @return \RHX\Model\Object\Employe
     */
    public function getEmploye($matricule) {
	$tableMatricule = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	return $tableMatricule->get($matricule);
    }

    /**
     * Récupérer un site
     * 
     * @param int $site
     * @return \RHX\Model\Object\Site
     */
    public function getSite($site) {
	$tableSite = new \RHX\Model\Table\SiteTable($this->getAdapter());
	return $tableSite->get($site);
    }

    /**
     * Récupérer tout les sites sauf le site en paramètre
     * 
     * @param int $except
     * @return \RHX\Model\Object\Site
     */
    public function getSiteList($except = -1) {
	$tableSite = new \RHX\Model\Table\SiteTable($this->getAdapter());
	return $tableSite->getSomeSites(array((int) $except));
    }

    /**
     * Ajouter un employé à un planning type
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param int $id
     * @param \RHX\Model\Object\EmployeDisponibilite $disponibilite
     * @return \RHX\Model\Object\EmployeTemplate
     */
    public function addToPlanningType(\RHX\Model\Object\Employe $employe, $id, $disponibilite = null) {
	$tableEmployeTemplate	 = new \RHX\Model\Table\EmployeTemplateTable($this->getAdapter());
	$template		 = new \RHX\Model\Object\EmployeTemplate($this->getAdapter());
	$dayName		 = array('lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche');
	$disponibilite		 = (is_null($disponibilite)) ? $employe->getDisponibilite() : $disponibilite;
	$calculator		 = new \RHX\Model\Object\XCalculator($this->getAdapter());
	foreach ($dayName as $day) {
	    $dayEntree		 = $day . '_entree';
	    $daySortie		 = $day . '_sortie';
	    $dayPause		 = $day . '_pause';
	    $dayRepas		 = $day . '_repas';
	    $dayCode		 = $day . '_code';
	    $template->$dayCode	 = $disponibilite->$day;
	    $template->$dayEntree	 = $disponibilite->$dayEntree;
	    $template->$daySortie	 = $disponibilite->$daySortie;
	    $template->$dayPause	 = $calculator->isPause($disponibilite->$dayEntree, $disponibilite->$daySortie) ? 1 : 0;
	    $template->$dayRepas	 = $calculator->isRepas($disponibilite->$dayEntree, $disponibilite->$daySortie) ? 1 : 0;
	}
	$template->template	 = $id;
	$template->matricule	 = $employe->matricule;
	$template->id		 = $tableEmployeTemplate->save($template);
	return $template;
    }

    /**
     * Ajouter un employé à tous les plannings type du site
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param int $siteId
     * @return Array
     */
    public function addToPlanningTypes(\RHX\Model\Object\Employe $employe, $siteId) {
	$tableTemplate		 = new \RHX\Model\Table\PlanningTemplateTable($this->getAdapter());
	$templates		 = $tableTemplate->getAllBySite($siteId);
	$employeTemplates	 = array();
	foreach ($templates as $template) {
	    $employeTemplates[] = $this->addToPlanningType($employe, $template->id);
	}
	return $employeTemplates;
    }

    /**
     * Ajouter au planning semaine
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param \RHX\Model\Object\Semaine $semaine
     * @param string $date
     * @return \RHX\Model\Object\PlanningSemaine
     */
    public function addToPlanningSemaine(\RHX\Model\Object\Employe $employe, \RHX\Model\Object\Semaine $semaine, $date) {
	$tablePlanning	 = new \RHX\Model\Table\PlanningSemaineTable($this->getAdapter());
	$dayName	 = array('lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche');


	$planning	 = new \RHX\Model\Object\PlanningSemaine($this->getAdapter());
	$disponibilite	 = $employe->getDisponibilite();
	$calculator	 = new \RHX\Model\Object\XCalculator($this->getAdapter());

	$dateRef = new RHDateTime($date);
	foreach ($dayName as $day) {
	    $dateDay = new RHDateTime($semaine->$day);

	    $dayEntree	 = $day . '_entree';
	    $daySortie	 = $day . '_sortie';
	    $dayPause	 = $day . '_pause';
	    $dayRepas	 = $day . '_repas';
	    $dayCode	 = $day . '_code';


	    if ($dateRef->isLT($dateDay) || $dateRef->isEqual($dateDay)) {
		$planning->$dayCode	 = $disponibilite->$day;
		$planning->$dayEntree	 = $disponibilite->$dayEntree;
		$planning->$daySortie	 = $disponibilite->$daySortie;
		$planning->$dayPause	 = $calculator->isPause($disponibilite->$dayEntree, $disponibilite->$daySortie) ? 1 : 0;
		$planning->$dayRepas	 = $calculator->isRepas($disponibilite->$dayEntree, $disponibilite->$daySortie) ? 1 : 0;
		$planning->$day		 = $semaine->$day;
	    }
	    else {
		$planning->$dayCode	 = XRules::EntreeSortie;
		$planning->$dayEntree	 = '00:00';
		$planning->$daySortie	 = '00:00';
		$planning->$dayPause	 = 0;
		$planning->$dayRepas	 = 0;
		$planning->$day		 = $semaine->$day;
	    }
	}
	$planning->matricule	 = $employe->matricule;
	$dataCp			 = $employe->getDataCP();
	$planning->coef		 = $dataCp['coef'];
	$planning->taux		 = $dataCp['taux'];
	$planning->hebdo	 = $dataCp['hebdo'];
	$planning->id		 = $tablePlanning->save($planning);
	$calculator->updateHeureTravail($planning, $tablePlanning);

	return $planning;
    }

    /**
     * Ajouter un employé aux plannings semaines
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param string $date
     * @return Array
     */
    public function addToPlanningSemaines(\RHX\Model\Object\Employe $employe, $date = null) {
	$planningListView	 = new \RHX\Model\View\PSPlanningView($this->getAdapter()); //$this->getService('View\PSPlanningView');
	$tablePeriode		 = new \RHX\Model\Table\PeriodeTable($this->getAdapter());
	$empManager		 = new \RHX\Model\Manager\EmployeManager($this->getAdapter());
	$periodeData		 = $tablePeriode->getPeriodeByDate($date);
	$periode		 = new \RHX\Model\Object\Periode($periodeData);
	$plannings		 = array();
	if ((int) $periode->id != 0) {
	    $tablePeriodeSemaine	 = new \RHX\Model\Table\PeriodeSemaineTable($this->getAdapter());
	    $semaines		 = $tablePeriodeSemaine->getSemainesByPeriode($periode->id);

	    //test chevauche periode            
	    if ($empManager->chevauchePeriodeEmploye($employe->matricule, $periode->id)) {
		foreach ($semaines as $semaine) {
		    // tester existence du PT applyed
		    $ps		 = $planningListView->getOne($periode->id, $semaine->id, $employe->site_id);
		    $hasPTApplyed	 = (boolean) $ps->template;
		    if ($hasPTApplyed) {
			$plannings[] = $this->addToPlanningSemaine($employe, $semaine, $date);
		    }
		}
	    }
	}
	return $plannings;
    }

    /**
     * Affichage du dialogue de changement de site
     * 
     * @param \Zend\Stdlib\Parameters $post
     * @return \Zend\View\Model\ViewModel
     */
    public function showChangeSiteDialog($post) {
	$dialog		 = new \Zend\View\Model\ViewModel();
	$employe	 = $this->getEmploye($post->matricule);
	$depart		 = $this->getSite($post->site);
	$arrivees	 = $this->getSiteList($depart->id);
	$firstDay	 = $this->getFirstDayOfNextMonth();
	$dialog->setVariables(array(
	    'employe'	 => $employe,
	    'depart'	 => $depart,
	    'arrivees'	 => $arrivees,
	    'firstDay'	 => $firstDay,
	));
	return $dialog;
    }

    /**
     * Application du changement de site
     * 
     * @param \Zend\Stdlib\Parameters $post
     * @return \Zend\View\Model\JsonModel
     */
    public function applyChangeSite($post) {
	$done	 = false;
	$error	 = '';
	try {
	    $data	 = $this->transfertSite($post->matricule, $post->arrivee, $post->date);
	    $done	 = true;
	}
	catch (\Exception $ex) {
	    $done	 = false;
	    $error	 = "Une erreur est survenue lors du traitement des informations<br>{$ex->getMessage()}";
	}
	$result = new \Zend\View\Model\JsonModel(array(
	    'done'	 => $done, 'error'	 => $error,
	));
	return $result;
    }

    /*
     */

    public function cancelTranfert($post) {
	$done	 = false;
	$error	 = '';
	try {
	    $data	 = $this->cancelTransfertSite($post->matricule, $post->site);
	    $done	 = true;
	}
	catch (\Exception $ex) {
	    $done	 = false;
	    $error	 = "Une erreur est survenue lors de l'annulation du transfert <br>{$ex->getMessage()}";
	}
	$result = new \Zend\View\Model\JsonModel(array(
	    'done'	 => $done, 'error'	 => $error,
	));
	return $result;
    }

    /* determine si un employe donnée empiete une periode donné
     * @param int $employeId matricule d'un employé
     * @param int $periodeId ID d'un periode
     * @return boolean
     */

    public function chevauchePeriodeEmploye($employeMatr, $periodeId) {

	$periodeTbl	 = new \RHX\Model\Table\PeriodeTable($this->getAdapter());
	$employeTable	 = new \RHX\Model\Table\EmployeTable($this->getAdapter());

	$employe = $employeTable->get($employeMatr);
	$periode = $periodeTbl->get($periodeId);

	$dateEntree	 = new RHDateTime($employe->contrat_debut);
	$hasDateDepart	 = $employe->contrat_fin != null && $employe->contrat_fin !== '' && $employe->contrat_fin !== '0000-00-00';
	$dateDepart	 = $hasDateDepart ? new RHDateTime($employe->contrat_fin) : null;

	$periodeDebut	 = new RHDateTime($periode->debut);
	$periodeFin	 = new RHDateTime($periode->fin);

	if ($dateEntree->isGT($periodeFin)) { ////echo"  dateEntree > periodeFin <br>" ;
	    $isChevauchePrd = FALSE;
	}
	else {
	    if ($dateEntree->isBetween($periodeDebut, $periodeFin)) // dateEntree between (periodeDebut periodeFin
		$isChevauchePrd = TRUE;
	    else { //  $dateEntree < $periodeDebut
		if (!$hasDateDepart)
		    $isChevauchePrd	 = TRUE;
		else
		    $isChevauchePrd	 = ($dateDepart->isLT($periodeDebut) ) ? FALSE : TRUE;
	    }
	}

	return $isChevauchePrd;
    }

    /**
     * Liste des employé d'une periode
     * 
     * @param int $siteId
     * @param int $periodeId
     * @param string $order
     * @return array
     */
    public function getEmployesByPeriode($siteId, $periodeId, $order = 'matricule asc') {
	// manager
	$employeManager	 = new \RHX\Model\Manager\EmployeManager($this->getAdapter());
	// tbl
	$tableEmploye	 = new \RHX\Model\Table\EmployeTable($this->getAdapter());

	$employes = null;
	if ((int) $siteId >= 0) {
	    $employes = $tableEmploye->getEmployesBySiteEx2($siteId, $order);
	}
	else {
	    $employes = $tableEmploye->getAll('nom1 ASC, prenom ASC');
	}

	$employesRes = array();

	foreach ($employes as $e) {
	    if ($employeManager->chevauchePeriodeEmploye($e->matricule, $periodeId)) {
		$employesRes[] = $e;
	    }
	}
	return $employesRes;
    }

    /**
     * Cloture du contrat de l'avenat en cours à la date specifée
     * 
     * @param \RHX\Model\Object\Employe $employe
     * @param string $date
     * @return array
     */
    private function closeContrat(\RHX\Model\Object\Employe $employe, $date = null) {
	$date				 = (is_null($date)) ? date('Y-m-d') : $date;
	$tableEmploye			 = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	$tableAvenant			 = new \RHX\Model\Table\AvenantTable($this->getAdapter());
	$employe->contrat_fin		 = $date;
	$employe->contrat_motif_depart	 = 0;
	$avenant			 = $employe->getAvenant();
	$avenant->fin			 = $date;
	$tableEmploye->save($employe);
	$tableAvenant->save($avenant);
	return array(
	    'avenant' => $avenant,
	);
    }

    /* Mettre à jour l' employé par rapport au tranfert effectué
     * @param \RHX\Model\Object\Employe $employe
     * @reutn array 
     */

    private function updateInfoTransfertEmploye(\RHX\Model\Object\Employe $employe) {
	$old_tranfert = $employe->transfert;
	if ($old_tranfert == 0) {
	    $new_tranfert = -9999;
	}
	elseif ($old_tranfert > 0) {
	    $new_tranfert = - $new_tranfert;
	}
	else {
	    throw new \Exception("Impossible de tranféré l'employé #" . $employe->matricule . " ");
	}
	$employe->transfert	 = $new_tranfert;
	$tableEmploye		 = new \RHX\Model\Table\EmployeTable($this->getAdapter());
	$tableEmploye->save($employe);

	return array(
	    'employe' => $employe
	);
    }

    private function setESPlanningSemaines(\RHX\Model\Object\Employe $employe, $date = null) {
	$planningListView	 = new \RHX\Model\View\PSPlanningView($this->getAdapter()); //$this->getService('View\PSPlanningView');
	$tablePeriode		 = new \RHX\Model\Table\PeriodeTable($this->getAdapter());
	$empManager		 = new \RHX\Model\Manager\EmployeManager($this->getAdapter());
	$periodeData		 = $tablePeriode->getPeriodeByDate($date);
	$periode		 = new \RHX\Model\Object\Periode($periodeData);
	$plannings		 = array();
	if ((int) $periode->id != 0) {
	    $tablePeriodeSemaine	 = new \RHX\Model\Table\PeriodeSemaineTable($this->getAdapter());
	    $semaines		 = $tablePeriodeSemaine->getSemainesByPeriode($periode->id);

	    //test chevauche periode            
	    if ($empManager->chevauchePeriodeEmploye($employe->matricule, $periode->id)) {
		foreach ($semaines as $semaine) {
		    // tester existence du PT applyed
		    $ps		 = $planningListView->getOne($periode->id, $semaine->id, $employe->site_id);
		    $hasPTApplyed	 = (boolean) $ps->template;
		    if ($hasPTApplyed) {
			$plannings[] = $this->setESPlanningSemaine($employe, $semaine, $date);
		    }
		}
	    }
	}
	return $plannings;
    }

    private function setESPlanningSemaine(\RHX\Model\Object\Employe $employe, \RHX\Model\Object\Semaine $semaine, $date) {
	$tablePlanning	 = new \RHX\Model\Table\PlanningSemaineTable($this->getAdapter());
	$dayName	 = array('lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche');


	$planning	 = $tablePlanning->getPlanningByDay($semaine->lundi, $employe->matricule);
	//$disponibilite	 = $employe->getDisponibilite();
	$calculator	 = new \RHX\Model\Object\XCalculator($this->getAdapter());

	$dateRef = new RHDateTime($date);
	foreach ($dayName as $day) {
	    $dateDay = new RHDateTime($semaine->$day);

	    $dayEntree	 = $day . '_entree';
	    $daySortie	 = $day . '_sortie';
	    $dayPause	 = $day . '_pause';
	    $dayRepas	 = $day . '_repas';
	    $dayCode	 = $day . '_code';


	    if ($dateRef->isLT($dateDay) || $dateRef->isEqual($dateDay)) {
		$planning->$dayCode	 = XRules::EntreeSortie;
		$planning->$dayEntree	 = '00:00';
		$planning->$daySortie	 = '00:00';
		$planning->$dayPause	 = 0;
		$planning->$dayRepas	 = 0;
		$planning->$day		 = $semaine->$day;
	    }
	    else {
		// RAS
	    }
	}
	$planning->matricule	 = $employe->matricule;
	$dataCp			 = $employe->getDataCP();
	$planning->coef		 = $dataCp['coef'];
	$planning->taux		 = $dataCp['taux'];
	$planning->hebdo	 = $dataCp['hebdo'];
	$planning->id		 = $tablePlanning->save($planning);
	$calculator->updateHeureTravail($planning, $tablePlanning);
    }

    /* supprime les planning semaine des future periode
     */

    private function erasePlanningSemaines(\RHX\Model\Object\Employe $employe, $date = null) {
	$tablePeriode		 = new \RHX\Model\Table\PeriodeTable($this->getAdapter());
	$planningListView	 = new \RHX\Model\View\PSPlanningView($this->getAdapter()); //$this->getService('View\PSPlanningView');
	$periodes		 = $tablePeriode->getFuturePeriode($date);

	foreach ($periodes as $periode) {
	    $tablePeriodeSemaine	 = new \RHX\Model\Table\PeriodeSemaineTable($this->getAdapter());
	    $semaines		 = $tablePeriodeSemaine->getSemainesByPeriode($periode->id);

	    foreach ($semaines as $semaine) {
		// tester existence du PT applyed
		$ps		 = $planningListView->getOne($periode->id, $semaine->id, $employe->site_id);
		$hasPTApplyed	 = (boolean) $ps->template;

		if ($hasPTApplyed) {
		    $this->erasePlanningSemaine($employe, $semaine);
		}
	    }
	}
    }

    /* Supprime une planning semaine pour un employé et semaine donnée
     * @param \RHX\Model\Object\Employe $employe 
     * @param \RHX\Model\Object\Semaines $semaine
     */

    private function erasePlanningSemaine(\RHX\Model\Object\Employe $employe, \RHX\Model\Object\Semaine $semaine) {
	$tablePlanning	 = new \RHX\Model\Table\PlanningSemaineTable($this->getAdapter());
	$ps		 = $tablePlanning->getPlanningByDay($semaine->lundi, $employe->matricule);
	$tablePlanning->erase($ps->id);
    }

    /**
     * Premier jour du mois suivant
     * 
     * @return \RHX\Helper\RHDateTime
     */
    public function getFirstDayOfNextMonth() {
	$date		 = new \DateTime();
	$date->modify('next month');
	$date->setDate((int) $date->format('Y'), (int) $date->format('m'), 1);
	$dateAffichage	 = new \RHX\Helper\RHDateTime($date->format('Y-m-d'));
	return $dateAffichage;
    }

}
